package com.hg.library.widget;

import android.app.Activity;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Display;
import android.view.KeyEvent;
import android.view.SoundEffectConstants;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Interpolator;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.FrameLayout;
import android.widget.HorizontalScrollView;

import com.hg.highglass_library.R;
import com.hg.library.utils.InputManager;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by ASUS-PC on 2016/6/10.
 */
public class CuteGridView extends HorizontalScrollView implements Member {

    private Context mContext;

    public FrameLayout parentLayout;

    private HiScroller hiScroller;

    private boolean isFocusAllowedMove = true;

    private boolean allowedRequestFocus = true;
    private int dx = 0;

    private int itemW;

    private int margin = 90;
    private OnItemClickListener onItemClickListener;
    private OnItemSelectedListener onSelectedItemListener;
    private OnItemMenuClickListener onItemMenuClickListener;
    private OnItemBackClickListener onItemBackClickListener;


    private List<View> viewList = new ArrayList<>();

    int displayWidth;

    public CuteGridView(Context context, AttributeSet attrs) throws NoSuchFieldException, IllegalAccessException {
        super(context, attrs);
        initView(context);
        initScroller(context);
        Activity activity = (Activity) context;
        Display defaultDisplay = activity.getWindowManager().getDefaultDisplay();
        setHorizontalScrollBarEnabled(false);
        displayWidth = defaultDisplay.getWidth();
    }

    private void initScroller(Context context) throws NoSuchFieldException, IllegalAccessException {
        Class aClass = getClass().getSuperclass();
        Field field = aClass.getDeclaredField("mScroller");
        field.setAccessible(true);
        field.set(this, hiScroller = new HiScroller(context));
        hiScroller.setMember(this);
    }

    private void initView(Context context) {
        LayoutParams layoutParams = new LayoutParams(-1, -1);
        parentLayout = new FrameLayout(context);
        parentLayout.setLayoutParams(layoutParams);
        addView(parentLayout);
        mContext = context;
    }

    public void setAdapter(CuteBaseAdapter adapter) {
        if (getChildCount() > 0) parentLayout.removeAllViews();
        if (viewList.size() > 0) viewList.clear();
        itemW = adapter.getItemWidth();
        for (int i = 0; i < adapter.getCount(); i++) {
            fromAdapterAddView(i,adapter);
        }
    }

    public void fromAdapterAddView(int i,CuteBaseAdapter adapter){
        View view;
        view = adapter.getView(null, i, adapter.getItem(i));
        LayoutParams layoutParams = new LayoutParams(adapter.getItemWidth(), adapter.getItemHeight());
        layoutParams.leftMargin = i / 2 * adapter.getItemWidth() + margin;

        layoutParams.topMargin = i % 2 == 1 ? margin + adapter.getItemHeight() : margin;
        layoutParams.bottomMargin = i % 2 == 1 ? margin : 0;
        if (i == adapter.getCount() - 1 || i == adapter.getCount() - 2) {
            layoutParams.rightMargin = margin;
        }
        view.setLayoutParams(layoutParams);
        view.setTag(R.id.cute_grid_item, i);
        viewList.add(view);
        view.setOnKeyListener(onKeyListener);
        view.setOnClickListener(onClickListener);
        if (view.getOnFocusChangeListener() == null)
            view.setOnFocusChangeListener(focusChangeListener);
        parentLayout.addView(view);
    }

    public List<View> getViewList() {
        return viewList;
    }

    public void scrollX(int dx) {
        scrollTo(dx, 0);
    }

    public View getChildView(int i) {
        return parentLayout.getChildAt(i);
    }

    public void setInterpolator(Interpolator interpolator) {
        hiScroller.setInterpolator(interpolator);
    }

    public void setScrollDuration(int duration) {
        hiScroller.setScrollDuration(duration);
    }

    public void setAllowedRequestFocus(boolean allowedRequestFocus) {
        this.allowedRequestFocus = allowedRequestFocus;
    }

    public boolean isAllowedRequestFocus() {
        return allowedRequestFocus;
    }

    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {

        if (InputManager.handledEnterKeyEvent(event.getKeyCode())) {
            return super.dispatchKeyEvent(event);
        } else if (event.getKeyCode() == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_DOWN) {
            return super.dispatchKeyEvent(event);
        } else if (event.getKeyCode() == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN) {
            if (onItemBackClickListener != null) onItemBackClickListener.onItemBackClick();
            return super.dispatchKeyEvent(event);
        }

        int keyCode = event.getKeyCode();

        // TODO: 2016/8/17 此段代码有可能移动到 onkeylistener
        if (keyCode == KeyEvent.KEYCODE_DPAD_UP
                || keyCode == KeyEvent.KEYCODE_DPAD_LEFT
                || keyCode == KeyEvent.KEYCODE_DPAD_RIGHT
                || keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
            if (!isFocusAllowedMove) return true;
        }
        return executeKeyEvent(event);
    }

    private static final String TAG = "CuteGridView";

    @Override
    public boolean executeKeyEvent(KeyEvent event) {
        if (event.getKeyCode() == KeyEvent.KEYCODE_DPAD_LEFT
                && event.getAction() == KeyEvent.ACTION_DOWN && allowedRequestFocus) {
            return executeKeyLeft(event);
        } else if (event.getKeyCode() == KeyEvent.KEYCODE_DPAD_RIGHT
                && event.getAction() == KeyEvent.ACTION_DOWN && allowedRequestFocus) {
            return executeKeyRight(event);
        } else if (event.getKeyCode() == KeyEvent.KEYCODE_DPAD_UP
                && event.getAction() == KeyEvent.ACTION_DOWN && allowedRequestFocus) {
            return executeKeyUp(event);
        } else if (event.getKeyCode() == KeyEvent.KEYCODE_DPAD_DOWN
                && event.getAction() == KeyEvent.ACTION_DOWN && allowedRequestFocus) {
            return executeKeyDown(event);
        }
        return super.executeKeyEvent(event);
    }

    public boolean executeKeyLeft(KeyEvent event) {
        View view = findFocus();

        if (view == null) return true;
        if (view.getTag(R.id.cute_grid_item) == null) return true;

        if (view != null) {
            int[] ints = new int[2];
            view.getLocationOnScreen(ints);
            int x = ints[0];
            int a = (int) (displayWidth / 2 + itemW * 0.5f) - margin / 2;

            if (x < a) {
                smoothScrollBy(x - a, 0);
            }
        }

        if (keyListener != null) {
            if (keyListener.onKeyLeft()) return true;
        }
        finderFocus(view, event.getKeyCode());
        return true;
    }

    public boolean executeKeyRight(KeyEvent event) {
        View view = findFocus();

        if (view == null) return true;
        if (view.getTag(R.id.cute_grid_item) == null) return true;

        if (view != null) {
            int[] ints = new int[2];
            view.getLocationOnScreen(ints);
            int x = ints[0];
            int a = (int) (displayWidth / 2 - itemW * 1.5f) - margin / 2;
            if (x > a && x < displayWidth / 2) {
                smoothScrollBy(x - a, 0);
            }
        }

        if (keyListener != null) {
            if (keyListener.onKeyRight()) return true;
        }
        finderFocus(view, event.getKeyCode());
        return true;
    }

    private void finderFocus(View view, int keycode) {
        int p = (int) view.getTag(R.id.cute_grid_item);
        if (keycode == KeyEvent.KEYCODE_DPAD_LEFT) {
            if (p - 2 >= 0) {
                viewList.get(p - 2).requestFocus();
                playSoundEffect(SoundEffectConstants.CLICK);
            }
        } else if (keycode == KeyEvent.KEYCODE_DPAD_RIGHT) {
            if (p + 2 <= viewList.size() - 1) {
                viewList.get(p + 2).requestFocus();
                playSoundEffect(SoundEffectConstants.CLICK);
            } else if (p + 1 <= viewList.size() - 1 && viewList.size() % 2 == 1) {
                viewList.get(p + 1).requestFocus();
                playSoundEffect(SoundEffectConstants.CLICK);
            }
        }
    }

    public boolean executeKeyUp(KeyEvent event) {

        if (keyListener != null) {
            if (keyListener.onKeyUp()) return true;
        }

        return super.executeKeyEvent(event);
    }

    public boolean executeKeyDown(KeyEvent event) {

        if (keyListener != null) {
            if (keyListener.onKeyDown()) return true;
        }

        return super.executeKeyEvent(event);
    }

    public void setScrollOffset(int dx) {
        this.dx = dx;
    }

    public int getScrollOffset() {
        return dx;
    }

    @Override
    public int scrollDuration(int duration) {
        return duration;
    }

    @Override
    public int scrollX(int startX, int dx) {
        dx = dx > startX ? dx + getScrollOffset() : dx - getScrollOffset();
        return dx;
    }

    private OnKeyListener onKeyListener = new OnKeyListener() {
        @Override
        public boolean onKey(View v, int keyCode, KeyEvent event) {
            if (InputManager.handledEnterKeyEvent(keyCode) && event.getAction() == KeyEvent.ACTION_UP) {
                playSoundEffect(SoundEffectConstants.CLICK);
                if (onItemClickListener != null)
                    onItemClickListener.onItemClick(null, v, (int) (v.getTag(R.id.cute_grid_item)), -1);
                return true;
            } else if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_DOWN) {
                playSoundEffect(SoundEffectConstants.CLICK);
                if (onItemMenuClickListener != null)
                    onItemMenuClickListener.onItemMenuClick(v, (int) (v.getTag(R.id.cute_grid_item)));
            }
            return false;
        }
    };

    private OnClickListener onClickListener = new OnClickListener() {
        @Override
        public void onClick(View v) {
            if (onItemClickListener != null)
                onItemClickListener.onItemClick(null, v, (int) (v.getTag(R.id.cute_grid_item)), -1);
        }
    };

    private OnFocusChangeListener focusChangeListener = new OnFocusChangeListener() {
        @Override
        public void onFocusChange(View v, boolean hasFocus) {
            if (onSelectedItemListener != null && hasFocus)
                onSelectedItemListener.onItemSelected(null, v, (int) (v.getTag(R.id.cute_grid_item)), -1);
        }
    };

    public boolean isFocusAllowedMove() {
        return isFocusAllowedMove;
    }

    public void setFocusAllowedMove(boolean focusMove) {
        isFocusAllowedMove = focusMove;
    }

    public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
        this.onItemClickListener = onItemClickListener;
    }

    public void setOnItemMenuClickListener(OnItemMenuClickListener onItemMenuClickListener) {
        this.onItemMenuClickListener = onItemMenuClickListener;
    }

    public void setOnItemBackClickListener(OnItemBackClickListener onItemBackClickListener) {
        this.onItemBackClickListener = onItemBackClickListener;
    }

    public interface OnItemMenuClickListener {
        void onItemMenuClick(View v, int position);
    }

    public interface OnItemBackClickListener {
        void onItemBackClick();
    }

    public void setOnSelectedItemListener(OnItemSelectedListener onSelectedItemListener) {
        this.onSelectedItemListener = onSelectedItemListener;
    }

    public void setScrollEnable(boolean scrollEnable) {
        hiScroller.setScrollEnable(scrollEnable);
    }

    private OnDispatchKeyListener keyListener;

    public void setOnDispatchKeyListener(OnDispatchKeyListener keyListener) {
        this.keyListener = keyListener;
    }

    public interface OnDispatchKeyListener {
        boolean onKeyUp();

        boolean onKeyDown();

        boolean onKeyLeft();

        boolean onKeyRight();
    }

    public ViewGroup getRootView(){
        return parentLayout;
    }
}
